package com.laomuji.android.mvvm.base

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.core.view.WindowCompat
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import com.laomuji.android.mvvm.base.lifecycle.LifecycleActivity
import com.laomuji.android.mvvm.utils.MyToast
import com.laomuji.android.mvvm.utils.ReflectionUtil
import com.laomuji.android.mvvm.utils.permission.PermissionUtil
import org.greenrobot.eventbus.EventBus

/**
 * 所有Activity的基类
 * 禁止旋转屏幕时重新走生命周期:在清单文件中设置:android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
 * @author laomuji666
 * @since 2024/2/20
 */
abstract class BaseActivity<VB : ViewBinding, VM : ViewModel> : LifecycleActivity() {
    /**
     * MVVM
     */
    open lateinit var viewBinding: VB
    open lateinit var viewModel: VM

    /**
     * 按两下返回键监听
     */
    protected object DoubleClick {
        private const val EXIT_CLICK_BACK_TIME: Long = 2000
        private var lastClickBackTime: Long = 0L
        /**
         * 计算 是否在 EXIT_CLICK_BACK_TIME 秒内 按下两次返回键
         * @return 是否按下了两次返回键
         */
        fun checkDoubleBackClick(): Boolean {
            val currentClickBackTime = System.currentTimeMillis()
            if (currentClickBackTime - lastClickBackTime > EXIT_CLICK_BACK_TIME) {
                lastClickBackTime = currentClickBackTime
                return false
            }
            return true
        }
    }

    /**
     * 主线程handler
     */
    private var mainHandlerIsInit = false
    open val mainHandler: Handler by lazy {
        mainHandlerIsInit = true
        Handler(Looper.getMainLooper())
    }

    /**
     * 是否已经销毁过了
     */
    private var isCleared = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        //恢复清理状态
        isCleared = false

        //设置顶部状态栏文字颜色
        setStatusBarTextColor(isLightStatusBarTextColor())

        //添加到MyApplication里
        BaseApplication.instance!!.addActivity(this)

        //注册EventBus
        if (isOpenEventBus() && !EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().register(this)
        }

        //初始化MVVM
        initViewBinding()
        initViewModel()

        //初始化页面和数据
        initView()
        initData()
    }

    override fun onDestroy() {
        clearPage()
        super.onDestroy()
    }

    override fun finish() {
        clearPage()
        super.finish()
    }

    /**
     * 结束Activity时清理
     */
    private fun clearPage(){
        //不重复清理数据
        if(isCleared){
            return
        }
        isCleared = true

        //移除当前Activity
        BaseApplication.instance!!.removeActivity(this)

        //注销EventBus
        if (isOpenEventBus() && EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }

        //移除handler
        if(mainHandlerIsInit){
            mainHandler.removeCallbacksAndMessages(null)
        }
    }


    /**
     * 初始化ViewBinding
     */
    private fun initViewBinding() {
        val viewBindingCls = ReflectionUtil.getGenericsClass<VB>(javaClass, 0) as Class<VB>
        val method = viewBindingCls.getMethod(
            "inflate",
            LayoutInflater::class.java
        )
        @Suppress("UNCHECKED_CAST")
        viewBinding = method.invoke(null,layoutInflater) as VB

        setContentView(viewBinding.root)
    }

    /**
     * 初始化ViewModel
     */
    private fun initViewModel() {
        val genericsClass = ReflectionUtil.getGenericsClass<VM>(javaClass, 1)
            ?: throw RuntimeException("ViewModel init Failed!")
        viewModel = ViewModelProvider(this)[genericsClass]
    }

    /**
     * 初始化页面
     * 包括对页面的初始化和获取Intent的数据
     */
    protected abstract fun initView()

    /**
     * 初始化数据
     * 包括从后台获取数据和监听ViewModel
     */
    protected abstract fun initData()

    /**
     * 顶部状态栏是否是亮色
     */
    protected open fun isLightStatusBarTextColor():Boolean = false

    /**
     * 默认不使用EventBus
     * @return 是否开启EventBus
     */
    protected open fun isOpenEventBus(): Boolean = false

    /**
     * 默认不开启按下两次返回键退出
     * @return 是否开启按下两次返回键退出,第一次按下返回键的提示文字
     */
    protected open fun isOpenDoubleBackExit(): Pair<Boolean, String> = Pair(false, "")

    /**
     * 默认开启隐藏输入法
     * @return 是否开启点击非EditText的区域隐藏输入法
     */
    protected open fun isOpenTouchHideInputMethod():Boolean = true


    /**
     * 按下两次返回键触发的事件
     * @return 是否拦截返回键事件
     */
    protected open fun onDoubleBackClick(): Boolean {
        BaseApplication.instance!!.exitApp()
        return false
    }

    /**
     * 拦截键盘按下事件
     * @return 按下一次时返回true,按下两次时调用父类的onKeyDown,正常情况会返回false
     */
    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        //拦截按下返回键,检查是否双击退出
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (isOpenDoubleBackExit().first) {
                if (!DoubleClick.checkDoubleBackClick()) {
                    //触发按下一次返回键的事件,弹出提示文本
                    MyToast.makeText(isOpenDoubleBackExit().second)
                    return true
                } else {
                    //触发按下两次返回键的事件
                    if (onDoubleBackClick()) {
                        return true
                    }
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    /**
     * 权限申请回调
     * @see [PermissionUtil]
     */
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray,
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        PermissionUtil.onRequestPermissionsResult()
    }

    /**
     * 拦截触摸事件
     */
    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        if (event.action == MotionEvent.ACTION_DOWN) {
            if (isOpenTouchHideInputMethod()){
                hideInputMethod(currentFocus, event)
            }
        }
        return super.dispatchTouchEvent(event)
    }

    /**
     * 点击非edit的位置,隐藏输入框
     */
    private fun hideInputMethod(v: View?, event: MotionEvent) {
        if (v is EditText) {
            val location = intArrayOf(0, 0)
            v.getLocationInWindow(location)
            val left = location[0]
            val top = location[1]
            val bottom = top + v.getHeight()
            val right = left + v.getWidth()
            if (!(event.x > left && event.x < right && event.y > top && event.y < bottom)) {
                val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
            }
        }
    }

    /**
     * 设置顶部状态栏文字颜色
     */
    protected fun setStatusBarTextColor(isLight:Boolean){
        val textColor = !isLight
        val decorView = window.decorView
        val windowInsetsController = WindowCompat.getInsetsController(window, decorView)
        if(windowInsetsController.isAppearanceLightStatusBars != textColor){
            windowInsetsController.isAppearanceLightStatusBars = textColor
        }
    }
}